#version 410

//#define DEBUG

out vec4 out_Color;

uniform sampler2D u_depthTX;
uniform sampler2D u_normalTX;
uniform sampler2D u_diffuseTX;
uniform sampler2D u_miscTX;

uniform mat4 u_invPersp;
uniform mat3 u_viewInvTrans;

uniform vec3 u_bottomColor;
uniform vec3 u_topColor;

uniform int u_gbufferView;

uniform int u_numLights;
uniform vec3 u_lightColor[8];
uniform vec3 u_lightDirection[8];

in vec2 fs_Texcoord;

const float directionalFactor = .4f * .1f;

// Code from : http://aras-p.info/texts/CompactNormalStorage.html

vec3 unpackNormal(in vec2 encNorm) {
	encNorm = encNorm*4.0f - 2.0f;
	float f = dot(encNorm, encNorm);
	float g = sqrt(1.0f -.25f*f);
	return vec3(encNorm*g,1.0f - .5f*f);
}

vec4 packFloatTo4x8(in float val) {
	uint a = floatBitsToInt(val);
	return vec4((bitfieldExtract(a,0,8))/256.0f,
				(bitfieldExtract(a,8,8))/256.0f,
				(bitfieldExtract(a,16,8))/256.0f,
				(bitfieldExtract(a,24,8))/256.0f);
}

float unpack4x8ToFloat(in vec4 val) {
	uint a = uint(val.x*256.0f+.5f) + 
	uint(val.y*256.0f+.5f)*256u + 
	uint(val.z*256.0f+.5f)*256u*256u+
	uint(val.w*256.0f+.5f)*256u*256u*256u;
	return uintBitsToFloat(a);
}

vec4 pack2FloatTo4x8(in vec2 val) {
	uint a = packUnorm2x16(val);
	return vec4((bitfieldExtract(a,0,8))/256.0f,
				(bitfieldExtract(a,8,8))/256.0f,
				(bitfieldExtract(a,16,8))/256.0f,
				(bitfieldExtract(a,24,8))/256.0f);
}

vec2 unpack4x8To2Float(in vec4 val) {
	uint a = uint(val.x*256.0f+.5f) + 
	uint(val.y*256.0f+.5f)*256u + 
	uint(val.z*256.0f+.5f)*256u*256u+
	uint(val.w*256.0f+.5f)*256u*256u*256u;
	return unpackUnorm2x16(a);
}

float linearizeDepth(float exp_depth, float near, float far) {
    return	(2 * near) / (far + near -  exp_depth * (far - near)); 
}

vec3 lightCalc(in vec3 dir, in vec3 normal, in vec3 color) {
	return color*(max(dot(-dir, normal), 0));
}

vec3 getVSPosition() {
	// Go from texture coordinate + depth to view space
	vec4 sPos = vec4(2.0f*fs_Texcoord.x - 1.0f, fs_Texcoord.y * 2.0f - 1.0f, 2.0*texture(u_depthTX, fs_Texcoord).x - 1.0f, 1.0f);
	sPos = u_invPersp * sPos;
	return sPos.xyz/sPos.w;
}

void main(void) {

	vec3 normal = unpackNormal(unpack4x8To2Float(texture(u_normalTX, fs_Texcoord)));
	
	vec3 color = vec3(0.0f);
	
	for(int i = 0; i < u_numLights; ++i)
		color += lightCalc(u_viewInvTrans*u_lightDirection[i], normal, u_lightColor[i]);

	out_Color = vec4(texture(u_diffuseTX, fs_Texcoord).xyz*color*directionalFactor, 1.0f);
}